{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在 Python 中,`@dispatch` 和 `@overload` 是两种用于实现类似重载功能的装饰器,但它们的用途和实现方式有显著区别:\n",
    "\n",
    "### 1. `@dispatch`(来自 `multipledispatch` 库)\n",
    "`@dispatch` 是第三方库 `multipledispatch` 提供的装饰器,用于实现**多分派**(Multiple Dispatch).它可以根据多个参数的类型来选择函数的实现.\n",
    "\n",
    "#### 特点:\n",
    "- **多分派**:可以根据多个参数的类型选择函数实现,而不仅仅是第一个参数.\n",
    "- **动态类型支持**:在运行时根据参数类型选择合适的实现.\n",
    "- **简洁的语法**:通过在装饰器中显式指定参数类型来定义不同的实现.\n",
    "\n",
    "#### 示例代码:\n",
    "```python\n",
    "from multipledispatch import dispatch\n",
    "\n",
    "@dispatch(int, int)\n",
    "def process(a, b):\n",
    "    print(f\"处理整数: {a} 和 {b}\")\n",
    "\n",
    "@dispatch(str)\n",
    "def process(value):\n",
    "    print(f\"处理字符串: {value}\")\n",
    "\n",
    "process(10, 20)  # 输出: 处理整数: 10 和 20\n",
    "process(\"hello\")  # 输出: 处理字符串: hello\n",
    "```\n",
    "\n",
    "### 2. `@overload`(来自 `typing` 模块)\n",
    "`@overload` 是 Python 标准库 `typing` 模块中的装饰器,主要用于**静态类型检查**,而不是运行时的函数重载.\n",
    "\n",
    "#### 特点:\n",
    "- **静态类型检查**:`@overload` 主要用于为类型检查器(如 `mypy`)提供额外的类型信息,帮助在静态分析阶段捕捉类型错误.\n",
    "- **运行时无效**:`@overload` 装饰的函数在运行时不会被直接调用,而是作为类型提示的一部分.\n",
    "- **需要实现**:实际的函数逻辑需要在其他地方实现,通常通过 `@overload` 装饰的函数需要与一个通用的实现函数配合使用.\n",
    "\n",
    "#### 示例代码:\n",
    "```python\n",
    "from typing import overload\n",
    "\n",
    "@overload\n",
    "def process(value: int) -> None:\n",
    "    ...\n",
    "\n",
    "@overload\n",
    "def process(value: str) -> None:\n",
    "    ...\n",
    "\n",
    "def process(value):\n",
    "    if isinstance(value, int):\n",
    "        print(f\"处理整数: {value}\")\n",
    "    elif isinstance(value, str):\n",
    "        print(f\"处理字符串: {value}\")\n",
    "\n",
    "process(10)  # 输出: 处理整数: 10\n",
    "process(\"hello\")  # 输出: 处理字符串: hello\n",
    "```\n",
    "\n",
    "### 3. 区别总结\n",
    "- **用途**:\n",
    "  - `@dispatch`:用于运行时的函数重载,支持多分派.\n",
    "  - `@overload`:用于静态类型检查,帮助类型检查器理解函数的多种重载形式.\n",
    "- **实现方式**:\n",
    "  - `@dispatch`:通过显式指定参数类型来实现运行时的分派.\n",
    "  - `@overload`:需要结合通用实现函数,仅在静态类型检查阶段生效.\n",
    "- **适用场景**:\n",
    "  - 如果需要在运行时根据参数类型动态选择函数实现,使用 `@dispatch`.\n",
    "  - 如果需要在静态类型检查阶段提供类型提示,使用 `@overload`.\n",
    "\n",
    "希望这些信息能帮助你更好地理解两者的区别和使用场景."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`multipledispatch` 支持以下类型的调度机制:\n",
    "\n",
    "1. **具体类型**:可以使用具体的 Python 类型(如 `int`、`str`、`float`、自定义类等)作为参数类型.\n",
    "   ```python\n",
    "   @dispatch(int)\n",
    "   def func(x):\n",
    "       print(\"Integer:\", x)\n",
    "   ```\n",
    "\n",
    "2. **联合类型(Union Types)**:支持使用元组表示多个类型,类似于 `isinstance` 的行为.\n",
    "   ```python\n",
    "   @dispatch((int, float))\n",
    "   def func(x):\n",
    "       print(\"Number:\", x)\n",
    "   ```\n",
    "\n",
    "3. **内置抽象类**:支持使用 Python 的内置抽象类(如 `collections.abc.Iterable`、`numbers.Number` 等).\n",
    "   ```python\n",
    "   from collections.abc import Iterable\n",
    "\n",
    "   @dispatch(Iterable)\n",
    "   def func(x):\n",
    "       print(\"Iterable:\", x)\n",
    "   ```\n",
    "\n",
    "4. **继承关系**:支持基于类的继承关系进行调度.子类会优先匹配更具体的父类.\n",
    "   ```python\n",
    "   class Parent:\n",
    "       pass\n",
    "\n",
    "   class Child(Parent):\n",
    "       pass\n",
    "\n",
    "   @dispatch(Parent)\n",
    "   def func(x):\n",
    "       print(\"Parent type\")\n",
    "\n",
    "   @dispatch(Child)\n",
    "   def func(x):\n",
    "       print(\"Child type\")\n",
    "   ```\n",
    "\n",
    "5. **变长参数调度**:支持不同数量的参数.\n",
    "   ```python\n",
    "   @dispatch(int, int)\n",
    "   def func(a, b):\n",
    "       print(\"Two integers:\", a, b)\n",
    "\n",
    "   @dispatch(int)\n",
    "   def func(a):\n",
    "       print(\"One integer:\", a)\n",
    "   ```\n",
    "\n",
    "6. **默认类型**:可以使用 `object` 作为默认类型,捕获所有未被其他具体类型覆盖的情况.\n",
    "   ```python\n",
    "   @dispatch(object)\n",
    "   def func(x):\n",
    "       print(\"Unknown type\")\n",
    "   ```\n",
    "\n",
    "### 不支持的类型\n",
    "- **`typing.Any`**:`multipledispatch` 不支持 `typing.Any`,因为它是类型提示工具,而不是具体的运行时类型.\n",
    "- **对角线调度**:不支持完全相同的参数类型(如 `@dispatch(a, a)`其中a是变量,则会出错.).\n",
    "\n",
    "通过这些支持的类型,`multipledispatch` 提供了灵活的多分派机制,能够根据参数的类型动态选择函数实现."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "This is a triangular element\n",
      "This is a quadrilateral element\n",
      "Processing triangular element\n",
      "Processing quadrilateral element\n",
      "Processing a number\n",
      "Processing an iterable and a number\n",
      "Processing an object\n",
      "Processing two integers\n"
     ]
    }
   ],
   "source": [
    "from typing import Any,List\n",
    "from multipledispatch import dispatch\n",
    "from collections.abc import Iterable\n",
    "from numbers import Number\n",
    "\n",
    "class elemBase:\n",
    "    def show():\n",
    "        raise NotImplementedError(\"elemBase.show() is not implemented\")\n",
    "    \n",
    "class elemTri(elemBase):\n",
    "    def show(self):\n",
    "        print(\"This is a triangular element\")\n",
    "        \n",
    "class elemQuad(elemBase):\n",
    "    def show(self):\n",
    "        print(\"This is a quadrilateral element\")\n",
    "        \n",
    "class elemTet(elemBase):\n",
    "    def show(self):\n",
    "        print(\"This is a tetrahedral element\")\n",
    "        \n",
    "class elemHex(elemBase):\n",
    "    def show(self):\n",
    "        print(\"This is a hexahedral element\")\n",
    "\n",
    "\n",
    "@dispatch(elemTri)\n",
    "def process(elem):\n",
    "    print(\"Processing triangular element\")\n",
    "@dispatch(elemQuad)\n",
    "def process(elem):\n",
    "    print(\"Processing quadrilateral element\")\n",
    "@dispatch(elemTet)\n",
    "def process(elem):\n",
    "    print(\"Processing tetrahedral element\")\n",
    "@dispatch(elemHex)\n",
    "def process(elem):\n",
    "    print(\"Processing hexahedral element\")\n",
    "@dispatch(Number)\n",
    "def process(num):\n",
    "    print(\"Processing a number\")\n",
    "@dispatch(Iterable,Number)\n",
    "def process(iter,number):\n",
    "    print(\"Processing an iterable and a number\")\n",
    "@dispatch(object)\n",
    "def process(obj):\n",
    "    print(\"Processing an object\")\n",
    "@dispatch(int,int)\n",
    "def process(a,b):\n",
    "    print(\"Processing two integers\")\n",
    "\n",
    "# Testing the code\n",
    "t = elemTri()\n",
    "q = elemQuad()\n",
    "t.show()\n",
    "q.show()\n",
    "process(t)\n",
    "process(q)\n",
    "process(12)\n",
    "process([1,2,3],4)\n",
    "process({'a':1,'b':2})\n",
    "process(1,2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle \\left[\\begin{matrix}\\frac{l^{3} \\left(\\theta_{1} - \\theta_{2}\\right) - 3 l \\theta_{1} - 3 w_{1} + 3 w_{2}}{l^{2}} & \\frac{l^{3} \\left(- \\theta_{1} + \\theta_{2}\\right) + 2 l \\theta_{1} + 2 w_{1} - 2 w_{2}}{l^{3}}\\end{matrix}\\right]$"
      ],
      "text/plain": [
       "Matrix([[(l**3*(theta1 - theta2) - 3*l*theta1 - 3*w1 + 3*w2)/l**2, (l**3*(-theta1 + theta2) + 2*l*theta1 + 2*w1 - 2*w2)/l**3]])"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sympy import *\n",
    "\n",
    "l,w1,w2,theta1,theta2 = symbols('l,w1,w2,theta1,theta2')\n",
    "\n",
    "A=Matrix([[1 ,l],\n",
    "            [2,3*l]])\n",
    "B=Matrix([[(w2-w1-theta1*l)/(l**2)],\n",
    "            [theta2*l-theta1*l]])\n",
    "\n",
    "[a2,a3]=A.inv()*B\n",
    "\n",
    "simplify(Matrix([a2,a3]).T)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle \\left[\\begin{matrix}\\frac{l^{3} \\left(\\theta_{1} - \\theta_{2}\\right) - 3 l \\theta_{1} - 3 w_{1} + 3 w_{2}}{l^{2}} & \\frac{l^{3} \\left(- \\theta_{1} + \\theta_{2}\\right) + 2 l \\theta_{1} + 2 w_{1} - 2 w_{2}}{l^{3}}\\end{matrix}\\right]$"
      ],
      "text/plain": [
       "Matrix([[(l**3*(theta1 - theta2) - 3*l*theta1 - 3*w1 + 3*w2)/l**2, (l**3*(-theta1 + theta2) + 2*l*theta1 + 2*w1 - 2*w2)/l**3]])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sympy import *\n",
    "\n",
    "l,w1,w2,theta1,theta2 = symbols('l,w1,w2,theta1,theta2')\n",
    "\n",
    "A=Matrix([[1 ,l],\n",
    "            [2,3*l]])\n",
    "B=Matrix([[(w2-w1-theta1*l)/(l**2)],\n",
    "            [theta2*l-theta1*l]])\n",
    "\n",
    "[a2,a3]=A.inv()*B\n",
    "\n",
    "simplify(Matrix([a2,a3]).T)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "pyNumSci",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.14"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
